//
//  WBRefreshControl.swift
//  Weibo
//
//  Created by Albert Zhu on 16/10/23.
//  Copyright © 2016年 Albert Zhu. All rights reserved.
//

import UIKit

let CZRefreshOffset: CGFloat = 64

/// 刷新状态
///
/// - Normal:      普通
/// - Pulling:     超过临界点，如果放手立即刷新
/// - WillRefresh: 已经放手刷新
enum CZRefreshState {
    case Normal
    case Pulling
    case WillRefresh
}

// 刷新控件，负责刷新相关业务逻辑处理
class WBRefreshControl: UIControl {
    
    /// 刷新控件父视图，weak防止循环引用
    weak var scrollView: UIScrollView?
    lazy var refreshView: CZRefreshView = CZRefreshView.refreshView()
    
    init() {
        super.init(frame: CGRect())
        
        setupUI()
    }
    
    required init?(coder aDecoder: NSCoder) {
        //        fatalError("init(coder:) has not been implemented")
        super.init(coder: aDecoder)
        
        setupUI()
    }
    
    override func willMove(toSuperview newSuperview: UIView?) {
        super.willMove(toSuperview: newSuperview)
        
        debugPrint(newSuperview)
        
        guard let sv = newSuperview as? UIScrollView else {return}
        
        scrollView = sv
        
        // KVO
        scrollView?.addObserver(self, forKeyPath: "contentOffset", options: [], context: nil)
    }
    
    override func removeFromSuperview() {
        // 视图销毁时要移除观察者，否则会引起崩溃
        superview?.removeObserver(self, forKeyPath: "contentOffset")
        
        super.removeFromSuperview()
    }
    
    // KVO调用方法
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        
        guard let sv = scrollView else {return}
        
        let height = sv.contentInset.top + sv.contentOffset.y
        
        if height > 0 {return}
        
        if sv.isDragging {
            if height < -CZRefreshOffset && refreshView.refreshState == .Normal {
                
                debugPrint("松开立即刷新")
                refreshView.refreshState = .Pulling
                
            }else if height >= -CZRefreshOffset && refreshView.refreshState == .Pulling {
                refreshView.refreshState = .Normal
                debugPrint("下拉开始刷新")
            }
        }else{
            if refreshView.refreshState == .Pulling {
                beginRefreshing()
                
                DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 1.0, execute: { 
                    self.sendActions(for: .valueChanged)

                })
            }
        }
        
        frame = CGRect(x: 0, y: 0, width: sv.bounds.width, height: height)
    }
}

extension WBRefreshControl {
    func setupUI() {
        backgroundColor = UIColor.white
        addSubview(refreshView)
        
        // 自动布局
        refreshView.translatesAutoresizingMaskIntoConstraints = false
        
        addConstraint(NSLayoutConstraint(item: refreshView, attribute: .centerX, relatedBy: .equal, toItem: self, attribute: .centerX, multiplier: 1.0, constant: 0))
        addConstraint(NSLayoutConstraint(item: refreshView, attribute: .bottom, relatedBy: .equal, toItem: self, attribute: .bottom, multiplier: 1.0, constant: 0))
        addConstraint(NSLayoutConstraint(item: refreshView, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: refreshView.bounds.width))
        addConstraint(NSLayoutConstraint(item: refreshView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: refreshView.bounds.height))
    }
    
    func beginRefreshing() {
        
        guard let sv = scrollView else {return}
        
        if refreshView.refreshState == .WillRefresh {return}
        refreshView.refreshState = .WillRefresh
        
        debugPrint("开始刷新")
        
        var inset = sv.contentInset
        inset.top += CZRefreshOffset
        sv.contentInset = inset
    }
    
    func endRefreshing() {
        
        guard let sv = scrollView else {return}
        if refreshView.refreshState != .WillRefresh {return}
        
        var inset = sv.contentInset
        inset.top -= CZRefreshOffset
        
        UIView.animate(withDuration: 0.25) {
            sv.contentInset = inset
        }
        refreshView.refreshState = .Normal
    }
}
